/**
 * 表单控件
 * 基础功能定义
 */
;( function( global, factory ) {

	"use strict";

	if ( typeof define === "function" && define.amd ) {
		// 兼容AMD规范
		define(['jquery', 'util/commonUtil', 'util/formElementManager', 'util/formRender', 'util/formSetting'], function(a, b, c, d, e){
			return factory(global, a, b, c, d, e);
		});
	} else {
		factory(global);
	}
} )( typeof window !== "undefined" ? window : this, function( window, $, commonUtil, formElementManager, formRender, formSetting ) {
	//console.log(formElementManager);
	//表单控件基类
	class BaseElement {
		/**
		let typeId,    //元素类型id，全局唯一标识
			tagName,   //元素tagName，dom标签
			describe,  //中文描述
			_propertyId, 模型属性id
			
			formGroupHtml = '<div class="form-group">',
			formGroupHtmlClose = '</div>',
			
			controlLabelHtml = '<label class="control-label">',
			controlLabelHtmlClose = '</label>',
			
			controlDivHtml = '<div class="input-group">',
			controlDivHtmlClose = '</div>',
			
			formControlHtml = '<input type="text" class="form-control" placeholder="请输入">',
			formControlHtmlClose = '',
			
			formWidth = 12,
			labelWidth = 3,
			inputWidth = 7;
			*/
		/**
		 * 参数通过对象传递，支持自定义参数
		 * {
		 * 	"typeId": "baseelement", //控件类型id，全局唯一
		 *  "show": {
		 * 	  "glyphicon": "" //glyphicon图标
		 *    "label": "" //拖拽控件显示名称
		 *  },
		 *  "draw": {
		 * 	   
		 *  }
		 * }
		 */
		constructor(obj) {
			if(typeof obj !== 'object') {
				throw '控件构造器需要参数';
			}
			if( !obj.typeId ) {
				throw '参数typeId必填';
			}
			commonUtil.deepCopy(this, obj);
			if(obj.domId) {
				//从页面已存在的html实例化组件对象
				this.dom = document.getElementById(obj.domId);
				this.$dom = $(this.dom);
				
				// TODO 从html中读取验证配置、事件配置等，作为初始值
				this._eventObj = {};//事件定义
				this._validateConfig = {};//验证配置
				{
					//读取验证配置
					let configs = ['rule', 'reg', 'regtitle', 'minlength', 'maxlength'];
					for(let i in configs) {
						let k = configs[i];
						if( this.$dom.attr( "data-validate-" + k ) ) {
							let v = this.$dom.attr( "data-validate-" + k );
							this._validateConfig[k] = v;
						}
					}
				}
				
				{
					//读取事件配置
					let ghost = this;
					this.$dom.next("[data-scriptFor]").each(function() {
						let thsE = $(this);
						let _eventName    = thsE.attr("data-eventName");
						let _eventContent = thsE.text();
						ghost._eventObj[_eventName] = _eventContent;
					});
				}
				
				this.required(this.$dom.attr("data-validate-required"));
				// ......
				this.id = obj.domId;
			} else {
				this.createDom();
				this._validateConfig = {};//验证配置
				this._eventObj = {};//事件定义
				//每次生产新对象，都需要放到formElementManager中进行管理
				//this.id = formElementManager.getId();
				this.id = commonUtil.domId($(this.dom));
			}
			this.label($(this.dom).find(".label-name").text()??"");
			formElementManager.set(this.id, this);
			
		}
		
		//模型属性id
		set propertyId(propertyId) {
			this._propertyId = propertyId;
		}
		get propertyId() {
			return this._propertyId;
		}
		//模型属性
		set property(property) {
			this._property = property;
			this.inputDom()?.attr({"id": property.propertyCode, "name": property.propertyCode});
			this.label(property.propertyName??"");
		}
		get property() {
			return this._property;
		}
		
		shown(flag) {
			if(typeof flag === 'undefined') {
				return this._property.__shown;
			}
			if( typeof this._property === 'object') {
				this._property.__shown = flag;
				let dragElement = $("#layout-left .draggable-element[data-property-id='" + this._propertyId + "']");
				flag ? dragElement.hide() : dragElement.show();
			}
		}
		
		/**
		 * 生成DOM元素
		 * 自定义控件需要覆盖此方法以生成自己的HTML DOM
		 * 
		 * 生成的DOM元素最好不使用带有float的样式，float会使元素布局脱离文档，无法使用拖拽排序
		 * bootstrap的 col-*-*带有float
		 * 
		 * **必须要覆写
		 * --覆写此方法注意事项：
		 *   1、必须要有一个用于提交数据的元素（或者绑定到一个隐藏的输入框），和属性对应的name属性
		 *   2、通过覆写inputDom方法，获取对应的用于表单提交的input元素(值类型组件需要，展示型组件不需要)
		 *   3、必须要包含在一个DOM元素中，拖拽元素会自动生成元素id用于处理各个业务，如果有同级元素会导致重复的id
		 * 
		 */
		createDom() {
			if(typeof this.dom === 'undefined') {
				let formGroup = document.createElement('div');
				formGroup.className = 'form-group';
				
				let controlLabel = document.createElement('label');
				controlLabel.className = 'control-label';
				controlLabel.innerText = '标题';
				
				let controlDiv = document.createElement('div');
				controlDiv.className = 'control-div';
				
				let controlGroupDiv = document.createElement('div');
				controlGroupDiv.className = 'if-input-group';
				
				let formControl = document.createElement('input');
				formControl.className = 'form-control';
				formControl.setAttribute("type", "text") ;
				
				let validateTextDiv = document.createElement('p');//验证提示信息
				validateTextDiv.className = 'validate-msg';
				
				let infoMsgDiv = document.createElement('p');//静态提示文本
				infoMsgDiv.className = 'static-info';
				
				
				formGroup.appendChild(controlLabel);
				formGroup.appendChild(controlDiv);
				controlDiv.appendChild(controlGroupDiv);
				controlDiv.appendChild(validateTextDiv);
				controlDiv.appendChild(infoMsgDiv);
				controlGroupDiv.appendChild(formControl);
				this.dom = formGroup;
				this.$dom = $(this.dom);
			}
			return this.dom;
		}
		
		/**
		 * 获取用于表单提交的input元素
		 * ** 值类型组件需要覆写，展示型组件可不用覆写
		 */
		inputDom() {
			//throw new Error("无法获取值对象");
		}
		
		appendTo(target) {
			target.append(this.dom);
		}
		/**
		 * 设置或获取控件label标签
		 * label文本内容支持html标签，可使用<br>换行
		 */
		label(text) {
			if(typeof text === 'undefined') {
				return this._label;
			}
			this._label = text;
			$(this.dom).find(".control-label .label-name").text(text);
		}
		
		/**
		 * 组件取值，设置值
		 * 这里提供默认方法，对inputDom()方法返回的元素进行取值、副值操作
		 */
		val(val) {
			if(typeof val === 'undefined') {
				return this.prefix() + (this.inputDom()?.val()??"") + this.suffix();
			}
			if(val) {
				if(this.prefix() && val.indexOf(this.prefix()) === 0) {
					val = val.substring(this.prefix().length);
				}
				if( this.suffix() && val.indexOf(this.suffix()) === (val.length - this.suffix().length) ) {
					val = val.substring(0, val.length - this.suffix().length);
				}
			}
			this.inputDom()?.val(val)??"";
		}
		
		/**
		 * 设置、获取 是否必填
		 */
		required(flag) {
			if(typeof flag === 'undefined') {
				//return this.$dom.find(".form-control").hasClass("validate-required");
				return this.$dom.attr("data-validate-required");
			}
			if(flag) {
				//this.$dom.find(".form-control").addClass("validate-required");
				this.$dom.attr("data-validate-required", true);
				if( this.$dom.find(".control-label .required-star").length == 0 ) {
					this.$dom.find(".control-label").prepend('<span class="required-star">*</span>');
				}
			} else {
				//this.$dom.find(".form-control").removeClass("validate-required");
				this.$dom.removeAttr("data-validate-required");
				this.$dom.find(".required-star").remove();
			}
		}
		
		
		/**
		 * 设置、获取 是否只读
		 */
		readonly(flag) {
			if(typeof flag === 'undefined') {
				return this._readonly??false;
			}
			this._readonly = flag;
			this.inputDom()?.prop("readonly", flag);
		}
		
		/**
		 * 模型字段只读属性
		 * 如果模型字段的readonly属性为true，则不能更改只读属性
		 */
		forceReadonly(flag) {
			if(typeof flag === 'undefined') {
				return this._forceReadonly;
			}
			this._forceReadonly = flag;
			this.readonly(flag);
			if(flag) {//只读取消必填
				this.required(false);
			}
		}
		
		/**
		 * 创建设置默认值的输入项
		 * 不同的组件设置默认值的方式需要由组件自己定义
		 */
		dom4SetDefaultValue() {
			
		}
		
		
		/**
		 * 设置默认值
		 * 默认值支持空值作为默认值，所以 清空默认值需要调用clearDefaultValue方法
		 */
		setDefaultValue(val) {
			this.defaultValue = val;
			this.$dom.attr("data-default-value", encodeURIComponent(val));
			this.inputDom()?.val(val);
		}
		
		/**
		 * 获取表单上设置的默认值
		 */
		getDefaultValue() {
			return this.defaultValue;
		}
		/**
		 * 清空默认值
		 */
		clearDefaultValue(val) {
			this.defaultValue = undefined;
			this.$dom.removeAttr("data-default-value");
			this.inputDom()?.val("");
		}
		
		/**
		 * 更新控件宽度
		 * width的取值为1-12的整数，对应栅格的宽度
		 * 
		 * **不需要覆写
		 * 
		 */
		updateWidth(width) {
			let formWrapperDom = this.dom.parentNode;
			//不使用style属性设置宽度，使用类名控制，方便屏幕适配
			if( formWrapperDom.hasAttribute("data-form-width") ) {
				let preWidth = formWrapperDom.getAttribute("data-form-width");
				formWrapperDom.classList.remove( "form-col-" + preWidth );
				formWrapperDom.removeAttribute("data-form-width");
			}
			if(width) {
				formWrapperDom.classList.add( "form-col-" + width );
				formWrapperDom.setAttribute("data-form-width", width);
			}
		}
		
		getFormWidth() {
			return this.dom.parentNode.getAttribute("data-form-width");
		}
		
		/**
		 * 更新/获取 控件前缀内容
		 * val为空时，删除前缀内容
		 */
		prefix(val) {
			if(typeof val === 'undefined') {
				let prefixDom = this.$dom.find(".input-group-addon-prefix");
				if(prefixDom.length) {
					return prefixDom.html();
				}
				return "";
			}
			let inputGroupDiv = this.$dom.find(".if-input-group");
			if(val) {
				inputGroupDiv.addClass("input-group");
				let prefixDom = this.$dom.find(".input-group-addon-prefix");
				if(!prefixDom.length) {
					prefixDom = $('<div class="input-group-addon input-group-addon-prefix"></div>');
					inputGroupDiv.prepend(prefixDom);
				}
				prefixDom.text(val);
			} else {
				this.$dom.find(".input-group-addon-prefix").remove();
				if(!this.$dom.find(".input-group-addon").length) {
					inputGroupDiv.removeClass("input-group");
				}
			}
		}
		
		/**
		 * 更新/获取 控件后缀内容
		 * val为空时，删除后缀内容
		 */
		suffix(val) {
			if(typeof val === 'undefined') {
				let suffixDom = this.$dom.find(".input-group-addon-suffix");
				if(suffixDom.length) {
					return suffixDom.html();
				}
				return "";
			}
			let inputGroupDiv = this.$dom.find(".if-input-group");
			if(val) {
				inputGroupDiv.addClass("input-group");
				let suffixDom = this.$dom.find(".input-group-addon-suffix");
				if(!suffixDom.length) {
					suffixDom = $('<div class="input-group-addon input-group-addon-suffix"></div>');
					inputGroupDiv.append(suffixDom);
				}
				suffixDom.text(val);
			} else {
				this.$dom.find(".input-group-addon-suffix").remove();
				if(!this.$dom.find(".input-group-addon").length) {
					inputGroupDiv.removeClass("input-group");
				}
			}
		}
		
		/**
		 * 设置、获取 提示文本
		 */
		helperText(val) {
			let helperTextParentDiv = this.$dom.find(".other-msg");
			if(typeof val === 'undefined') {
				return helperTextParentDiv.find(".helper-text pre").html();
			}
			helperTextParentDiv.find(".helper-text").remove();
			if(val) {
				helperTextParentDiv.append('<div class="helper-text"><pre></pre></div>');
				helperTextParentDiv.find(".helper-text pre").text(val);
			}
		}
		
		/**
		 * 设置、获取 校验规则
		 */
		validateRule(val) {
			if(typeof val === 'undefined') {
				return this._validateRule;
			}
			this._validateRule = val;
			if(val) {
				this.$dom.attr("data-validate-rule", val);
			} else {
				this.$dom.removeAttr("data-validate-rule");
			}
		}
		
		/**
		 * 设置、获取 自定义正则
		 */
		validateReg(val) {
			if(typeof val === 'undefined') {
				return this._validateReg;
			}
			this._validateReg = val;
			if(val) {
				this.$dom.attr("data-validate-reg", val);
			} else {
				this.$dom.removeAttr("data-validate-reg");
			}
		}
		
		/**
		 * 设置、获取 自定义正则校验提示
		 */
		validateRegTitle(val) {
			if(typeof val === 'undefined') {
				return this._validateRegTitle;
			}
			this._validateRegTitle = val;
			if(val) {
				this.$dom.attr("data-validate-regtitle", val);
			} else {
				this.$dom.removeAttr("data-validate-regtitle");
			}
		}
		
		/**
		 * 设置、获取 校验配置
		 * 内置方法，不需要覆写
		 */
		validateConfig(conf) {
			if(typeof conf === 'undefined') {
				return this._validateConfig;
			}
			this._validateConfig = conf;
			
			//内置规则、自定义正则， 自定义正则提示， 最小长度， 最大长度
			let configs = ['rule', 'reg', 'regtitle', 'minlength', 'maxlength'];
			for(let i in configs) {
				let k = configs[i];
				let v = conf[k];
				if(v) {
					this.$dom.attr("data-validate-" + k, v);
				} else {
					this.$dom.removeAttr("data-validate-" + k);
				}
			}
		}
		
		/**
		 * 设置或获取事件
		 * 事件对象：{
		 * 	"eventName" : "eventScript"
		 * }
		 * eventName为绑定的事件名称，不用前缀on
		 * eventScript为脚本内容
		 * 
		 */
		events(eventObj) {
			if(typeof eventObj === "undefined") {
				return this._eventObj;
			}
			Object.assign(this._eventObj, eventObj);
			let domId = this.id;
			let eventName = Object.keys(eventObj)[0];
			let scriptId = "script-" + domId + "-" + eventName;
			let scriptWrap = $("#" + scriptId);
			if(!scriptWrap.length) {
				scriptWrap = $('<pre id="' + scriptId + '" data-eventName="' + eventName + '" data-scriptFor="' + domId + '" style="display:none;"></pre>');
				$(this.dom).after(scriptWrap);
			}
			scriptWrap.text(eventObj[eventName]);
		}
		
		/**
		 * 移除事件
		 */
		removeEvent(eventName) {
			delete this._eventObj[eventName];
			let domId = this.id;
			let scriptId = "script-" + domId + "-" + eventName;
			let scriptWrap = $("#" + scriptId);
			if(scriptWrap.length) {
				scriptWrap.remove();
			}
		}
		
		/**
		 * 定义表单设置项
		 */
		formSets() {
			//console.log(formSetting);
			if(typeof this.settingItems === 'undefined') {
				this.settingItems = [
				formSetting.labelName, formSetting.formWidth, formSetting.requireAndReadonly, 
				formSetting.bind2ModelProperty,
				formSetting.defaultValue,
				formSetting.helperText, formSetting.helperTextColor, formSetting.validate
				];
			}
			return this.settingItems;
		}
		
	}
	
	return BaseElement;
} );